-
Notifications
You must be signed in to change notification settings - Fork 265
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add: columns to Eth2Processor
and BlockProcessor
#6862
Conversation
|
||
let kzgCommits = | ||
signedBlock.message.body.blob_kzg_commitments.asSeq | ||
if dataColumns.len > 0 and kzgCommits.len > 0: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't seem to actually use kzgCommits
though, aside from this check?
(Also, if it's just checking len
, it shouldn't need asSeq
)
for dc in data_columns: | ||
if dc.index in custody_columns: | ||
final_columns.add dc | ||
dataColumnRefs = Opt.some(final_columns.mapIt(newClone(it))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why even create the non-ref
final_columns
to begin with, only to mapIt
immediately?
Once you know you're going to set dataColumnRefs = Opt.some ...
, can build it up in place.
func getDataColumnForkCode(fork: ConsensusFork): uint64 = | ||
case fork | ||
of ConsensusFork.Fulu: | ||
uint64(MaxForksCount) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because of invalid code range it provides invalid codes which overlaps with blobs range.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
resolved in a7af551
@@ -132,6 +135,27 @@ proc getShortMap*[T](req: SyncRequest[T], | |||
res.add('|') | |||
res | |||
|
|||
proc getShortMap*[T](req: SyncRequest[T], | |||
data: openArray[ref DataColumnSidecar]): string = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like this code is based on old and ugly version of blobs map, but it was recently changed to more suitable map format. So the idea is to show how blobs being distributed over the range request, so now it could look like
12..............................
, which means that for request range there was returned 1 blob for first block in range and 2 blobs for second one, all other blocks are without blobs, it looks like you still using MAX_BLOBS_PER_BLOCK
constant (i'm not sure is it appropriate) but if it so - please change this procedure to new version.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm also confused about the usage of MAX_BLOBS_PER_BLOCK
. It seems like NUMBER_OF_COLUMNS
(https://github.com/ethereum/consensus-specs/blob/v1.5.0-beta.1/specs/fulu/p2p-interface.md#configuration for example) is more relevant.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If NUMBER_OF_COLUMNS* = 128
new short format map should be invented, probably we should use 2 letters for single block, but it definitely should be changed from that version you are using.
data: openArray[Slot]): | ||
Result[void, cstring] = | ||
if data.len == 0: | ||
# Impossible to verify empty response |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe a nit, I guess? But it's clearly not impossible, since this function does it (affirmatively).
I'd call this something akin to https://en.wikipedia.org/wiki/Vacuous_truth -- maybe vacuously valid.
MsgSource.gossip, parentBlck.unsafeGet().asSigned(), blobs, | ||
Opt.none(DataColumnSidecars)) | ||
|
||
var columnsOk = true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nimbus-eth2/beacon_chain/gossip_processing/block_processor.nim
Lines 597 to 639 in 5f169d9
let | |
parent_root = signedBlock.message.parent_root | |
parentBlck = dag.getForkedBlock(parent_root) | |
if parentBlck.isSome(): | |
var blobsOk = true | |
let blobs = | |
withBlck(parentBlck.get()): | |
when consensusFork >= ConsensusFork.Deneb: | |
var blob_sidecars: BlobSidecars | |
for i in 0 ..< forkyBlck.message.body.blob_kzg_commitments.len: | |
let blob = BlobSidecar.new() | |
if not dag.db.getBlobSidecar(parent_root, i.BlobIndex, blob[]): | |
blobsOk = false # Pruned, or inconsistent DB | |
break | |
blob_sidecars.add blob | |
Opt.some blob_sidecars | |
else: | |
Opt.none BlobSidecars | |
if blobsOk: | |
debug "Loaded parent block from storage", parent_root | |
self[].enqueueBlock( | |
MsgSource.gossip, parentBlck.unsafeGet().asSigned(), blobs, | |
Opt.none(DataColumnSidecars)) | |
var columnsOk = true | |
let columns = | |
withBlck(parentBlck.get()): | |
when consensusFork >= ConsensusFork.Fulu: | |
var data_column_sidecars: DataColumnSidecars | |
for i in self.dataColumnQuarantine[].custody_columns: | |
let data_column = DataColumnSidecar.new() | |
if not dag.db.getDataColumnSidecar(parent_root, i.ColumnIndex, data_column[]): | |
columnsOk = false | |
break | |
data_column_sidecars.add data_column | |
Opt.some data_column_sidecars | |
else: | |
Opt.none DataColumnSidecars | |
if columnsOk: | |
debug "Loaded parent block from storage", parent_root | |
self[].enqueueBlock( | |
MsgSource.gossip, parentBlck.unsafeGet().asSigned(), Opt.none(BlobSidecars), | |
columns) |
It looks like:
- for a pre-Deneb block (still potentially relevant while genesis syncing, for example) or a Deneb/Electra block with no blobs (less common than before, but it happens), the
blobsOk
loop will be vacuously valid (no blobs means no invalid blobs, andblobsOk
is initialized totrue
), so
nimbus-eth2/beacon_chain/gossip_processing/block_processor.nim
Lines 617 to 619 in 5f169d9
self[].enqueueBlock( MsgSource.gossip, parentBlck.unsafeGet().asSigned(), blobs, Opt.none(DataColumnSidecars))
will run, but because thecolumnsOk
-based check separately/independently enqueues blocks and has the same vacuously-valid logic,
nimbus-eth2/beacon_chain/gossip_processing/block_processor.nim
Lines 635 to 637 in 5f169d9
if columnsOk: debug "Loaded parent block from storage", parent_root self[].enqueueBlock( enqueueBlock(...)
the same block again.
In general, I think but haven't enumerated all cases that for the usual valid-blobs-or-columns case (either) the vacuous-truth aspect means that it will typically double-enqueueBlock
things (blobs but not columns: the columns check is vacuously true, and the blobs check might be, if the blobs are valid).
Actually, this is even more -- it means that because blocks will have one or the other, all blocks will be either vacuously valid here for either blobs or columns and get enqueued at least once, so this opens a security bypass in block_processor
.
|
@@ -549,10 +629,28 @@ proc storeBlock( | |||
Opt.some blob_sidecars | |||
else: | |||
Opt.none BlobSidecars | |||
if blobsOk: | |||
# Blobs and columns can never co-exist in the same block | |||
doAssert blobs.isSome and columns.isSome |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How does this assert that "Blobs and columns can never co-exist in the same block"?
For this to be the case, exactly one of blobs.isSome
and columns.isSome
should be true. blobs.isSome and columns.isSome
would, rather, imply precisely that a block has both blobs and columns.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
resolved, however, again, if you have better suggestions, most welcome
# Blobs and columns can never co-exist in the same block | ||
doAssert blobs.isSome and columns.isSome | ||
# Block has neither blob sidecar nor data column sidecar | ||
if blobs.isNone and columns.isNone: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
blobs.isSome and columns.isSome
implies not-blobs.isNone and columns.isNone
. The only way this condition ever holds is when the assertion has already fired/caused a Defect
, i.e. the body of this if
is unreachable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is resolved, however, if you want to do another pass of reviews around here, sure
mixin getScore, `==` | ||
|
||
logScope: | ||
peer_score = peer.getScore() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's only one log
statement in this function -- not sure logScope
is useful?
Also, haven't checked if status-im/nim-chronicles#121 still applies, but at least at one point, logScope
didn't work in generic functions, of which this one.
Closed pending reworking/rebasing |
succeeded by #6945 |
No description provided.